package com.example.bitoperation;

import java.util.Arrays;

/**
 * 给定一个整数数组 nums，其中恰好有两个元素只出现一次，其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。
 * 进阶：你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现？
 * <p>
 * 示例 1：
 * 输入：nums = [1,2,1,3,2,5]
 * 输出：[3,5]
 * 解释：[5, 3] 也是有效的答案。
 * <p>
 * 示例 2：
 * 输入：nums = [-1,0]
 * 输出：[-1,0]
 */
public class Leetcode260_SingleNumberIII {

    public static void main(String[] args) {
        int[] num = {1, 2, 1, 3, 2, 5};
        int[] res = new Solution().singleNumber(num);
        Arrays.stream(res).forEach(e -> System.out.println(e));
    }

    static class Solution {
        /**
         * 位运算
         * 以[1,2,1,3,2,5]为例
         * xorSum = 5 ^ 3 = 6(0b110)  (最终这个结果的二进制为1的位置上x1和x2是不相同的)
         * lowBitNum = 2(0b010)
         * <p>
         * 最后想从xorSum分离出 x1, x2就可以以lowBitNum & num[i] == 0 为分界将数组分成两部分，
         * 但是由于 a ^ a = 0，也就是那些相同的数字虽然被分成两部分，但是分出的每部分最终都异或得到了0
         * 那么最终只会有：
         * xorSum ^ x1 = x2
         * xorSum ^ x2 = x1
         *
         * @param nums
         * @return
         */
        public int[] singleNumber(int[] nums) {
            int[] res = new int[2];
            int xorSum = 0;
            for (int num : nums) {
                xorSum ^= num;
            }
            int lowBitNum = xorSum & (-xorSum);
            for (int num : nums) {
                if ((lowBitNum & num) != 0) res[0] ^= num;
                else res[1] ^= num;

            }
            return res;
        }
    }
}
